home *** CD-ROM | disk | FTP | other *** search
- /*
- vmsify.c
-
- Module for vms <-> unix file name conversion
-
- Written by Klaus Kämpf (kkaempf@progis.de)
- of proGIS Software, Aachen, Germany
-
- */
-
- #include <string.h>
- #include <ctype.h>
-
- #if VMS
- #include <unixlib.h>
- #include <stdlib.h>
- #include <jpidef.h>
- #include <descrip.h>
- #include <uaidef.h>
- #include <ssdef.h>
- #include <starlet.h>
- #include <lib$routines.h>
- /* Initialize a string descriptor (struct dsc$descriptor_s) for an
- arbitrary string. ADDR is a pointer to the first character
- of the string, and LEN is the length of the string. */
-
- #define INIT_DSC_S(dsc, addr, len) do { \
- (dsc).dsc$b_dtype = DSC$K_DTYPE_T; \
- (dsc).dsc$b_class = DSC$K_CLASS_S; \
- (dsc).dsc$w_length = (len); \
- (dsc).dsc$a_pointer = (addr); \
- } while (0)
-
- /* Initialize a string descriptor (struct dsc$descriptor_s) for a
- NUL-terminated string. S is a pointer to the string; the length
- is determined by calling strlen(). */
-
- #define INIT_DSC_CSTRING(dsc, s) INIT_DSC_S(dsc, s, strlen(s))
- #endif
-
- /*
- copy 'from' to 'to' up to but not including 'upto'
- return 0 if eos on from
- return 1 if upto found
-
- return 'to' at last char + 1
- return 'from' at match + 1 or eos if no match
-
- if as_dir == 1, change all '.' to '_'
- else change all '.' but the last to '_'
- */
-
- static int
- copyto (char **to, char **from, char upto, int as_dir)
- {
- char *s;
-
- s = strrchr (*from, '.');
-
- while (**from)
- {
- if (**from == upto)
- {
- do
- {
- (*from)++;
- }
- while (**from == upto);
- return 1;
- }
- if (**from == '.')
- {
- if ((as_dir == 1)
- || (*from != s))
- **to = '_';
- else
- **to = '.';
- }
- else
- {
- if (islower (**from))
- **to = toupper (**from);
- else
- **to = **from;
- }
- (*to)++;
- (*from)++;
- }
-
- return 0;
- }
-
-
- /*
- get translation of logical name
-
- */
-
- static char *
- trnlog (char *name)
- {
- int stat;
- static char reslt[1024];
- $DESCRIPTOR (reslt_dsc, reslt);
- short resltlen;
- struct dsc$descriptor_s name_dsc;
- char *s;
-
- INIT_DSC_CSTRING (name_dsc, name);
-
- stat = lib$sys_trnlog (&name_dsc, &resltlen, &reslt_dsc);
-
- if ((stat&1) == 0)
- {
- return "";
- }
- if (stat == SS$_NOTRAN)
- {
- return "";
- }
- reslt[resltlen] = '\0';
-
- s = (char *)malloc (resltlen+1);
- if (s == 0)
- return "";
- strcpy (s, reslt);
- return s;
- }
-
- enum namestate { N_START, N_DEVICE, N_OPEN, N_DOT, N_CLOSED, N_DONE };
-
- /*
- convert unix style name to vms style
- type = 0 -> name is a full name (directory and filename part)
- type = 1 -> name is a directory
- type = 2 -> name is a filename without directory
-
- The following conversions are applied
- (0) (1) (2)
- input full name dir name file name
-
- 1 ./ <cwd> [] <current directory>.dir
- 2 ../ <home of cwd> <home of cwd> <home of cwd>.dir
-
- 3 // <dev of cwd>: <dev of cwd>:[000000] <dev of cwd>:000000.dir
- 4 //a a: a: a:
- 5 //a/ a: a: a:000000.dir
-
- 9 / [000000] [000000] 000000.dir
- 10 /a [000000]a [a] [000000]a
- 11 /a/ [a] [a] [000000]a.dir
- 12 /a/b [a]b [a.b] [a]b
- 13 /a/b/ [a.b] [a.b] [a]b.dir
- 14 /a/b/c [a.b]c [a.b.c] [a.b]c
- 15 /a/b/c/ [a.b.c] [a.b.c] [a.b]c.dir
-
- 16 a a [.a] a
- 17 a/ [.a] [.a] a.dir
- 18 a/b [.a]b [.a.b] [.a]b
- 19 a/b/ [.a.b] [.a.b] [.a]b.dir
- 20 a/b/c [.a.b]c [.a.b.c] [.a.b]c
- 21 a/b/c/ [.a.b.c] [.a.b.c] [.a.b]c.dir
-
- 22 a.b.c a_b.c [.a_b_c] a_b_c.dir
-
- 23 [x][y]z [x.y]z [x.y]z [x.y]z
- 24 [x][.y]z [x.y]z [x.y]z [x.y]z
-
- 25 filenames with '$' are left unchanged if they contain no '/'
- 25 filenames with ':' are left unchanged
- 26 filenames with a single pair of '[' ']' are left unchanged
-
- the input string is not written to
- */
-
- char *
- vmsify (name, type)
- char *name;
- int type;
- {
- /* max 255 device
- max 39 directory
- max 39 filename
- max 39 filetype
- max 5 version
- */
- #define MAXPATHLEN 512
-
- enum namestate nstate;
- static char vmsname[MAXPATHLEN+1];
- char *fptr;
- char *vptr;
- char *s,*s1;
- int as_dir;
- int count;
-
- if (name == 0)
- return 0;
- fptr = name;
- vptr = vmsname;
- nstate = N_START;
-
- /* case 25a */
-
- s = strpbrk (name, "$:");
- if (s != 0)
- {
- if (*s == '$')
- {
- if (strchr (name, '/') == 0)
- {
- return name;
- }
- }
- else
- {
- return name;
- }
- }
-
- /* case 26 */
-
- s = strchr (name, '[');
-
- if (s != 0)
- {
- s1 = strchr (s+1, '[');
- if (s1 == 0)
- {
- return name; /* single [, keep unchanged */
- }
- s1--;
- if (*s1 != ']')
- {
- return name; /* not ][, keep unchanged */
- }
-
- /* we have ][ */
-
- s = name;
-
- /* s -> starting char
- s1 -> ending ']' */
-
- do
- {
- strncpy (vptr, s, s1-s); /* copy up to but not including ']' */
- vptr += s1-s;
- if (*s1 == 0)
- break;
- s = s1 + 1; /* s -> char behind ']' */
- if (*s != '[') /* was '][' ? */
- break; /* no, last ] found, exit */
- s++;
- if (*s != '.')
- *vptr++ = '.';
- s1 = strchr (s, ']');
- if (s1 == 0) /* no closing ] */
- s1 = s + strlen (s);
- }
- while (1);
-
- *vptr++ = ']';
-
- fptr = s;
-
- }
-
- else /* no [ in name */
-
- {
-
- int state;
- int rooted = 1; /* flag if logical is rooted, else insert [000000] */
-
- state = 0;
-
- do
- {
-
- switch (state)
- {
- case 0: /* start of loop */
- if (*fptr == '/')
- {
- fptr++;
- state = 1;
- }
- else if (*fptr == '.')
- {
- fptr++;
- state = 10;
- }
- else
- state = 2;
- break;
-
- case 1: /* '/' at start */
- if (*fptr == '/')
- {
- fptr++;
- state = 3;
- }
- else
- state = 4;
- break;
-
- case 2: /* no '/' at start */
- s = strchr (fptr, '/');
- if (s == 0) /* no '/' (16) */
- {
- if (type == 1)
- {
- strcpy (vptr, "[.");
- vptr += 2;
- }
- copyto (&vptr, &fptr, 0, (type==1));
- if (type == 1)
- *vptr++ = ']';
- state = -1;
- }
- else /* found '/' (17..21) */
- {
- if ((type == 2)
- && (*(s+1) == 0)) /* 17(2) */
- {
- copyto (&vptr, &fptr, '/', 1);
- state = 7;
- }
- else
- {
- strcpy (vptr, "[.");
- vptr += 2;
- copyto (&vptr, &fptr, '/', 1);
- nstate = N_OPEN;
- state = 9;
- }
- }
- break;
-
- case 3: /* '//' at start */
- while (*fptr == '/') /* collapse all '/' */
- fptr++;
- if (*fptr == 0) /* just // */
- {
- char cwdbuf[MAXPATHLEN+1];
-
- s1 = getcwd(cwdbuf, MAXPATHLEN);
- if (s1 == 0)
- {
- return ""; /* FIXME, err getcwd */
- }
- s = strchr (s1, ':');
- if (s == 0)
- {
- return ""; /* FIXME, err no device */
- }
- strncpy (vptr, s1, s-s1+1);
- vptr += s-s1+1;
- state = -1;
- break;
- }
-
- s = vptr;
-
- if (copyto (&vptr, &fptr, '/', 1) == 0) /* copy device part */
- {
- *vptr++ = ':';
- state = -1;
- break;
- }
- *vptr = ':';
- nstate = N_DEVICE;
- if (*fptr == 0) /* just '//a/' */
- {
- strcpy (vptr+1, "[000000]");
- vptr += 9;
- state = -1;
- break;
- }
- *vptr = 0;
- /* check logical for [000000] insertion */
- s1 = trnlog (s);
- if (*s1 != 0)
- { /* found translation */
- char *s2;
- for (;;) /* loop over all nested logicals */
- {
- s2 = s1 + strlen (s1) - 1;
- if (*s2 == ':') /* translation ends in ':' */
- {
- s2 = trnlog (s1);
- free (s1);
- if (*s2 == 0)
- {
- rooted = 0;
- break;
- }
- s1 = s2;
- continue; /* next iteration */
- }
- if (*s2 == ']') /* translation ends in ']' */
- {
- if (*(s2-1) == '.') /* ends in '.]' */
- {
- if (strncmp (fptr, "000000", 6) != 0)
- rooted = 0;
- }
- else
- {
- strcpy (vmsname, s1);
- s = strchr (vmsname, ']');
- *s = '.';
- nstate = N_DOT;
- vptr = s;
- }
- }
- break;
- }
- free (s1);
- }
- else
- rooted = 0;
-
- if (*vptr == 0)
- {
- nstate = N_DEVICE;
- *vptr++ = ':';
- }
- else
- vptr++;
-
- if (rooted == 0)
- {
- strcpy (vptr, "[000000.");
- vptr += 8;
- s1 = vptr-1;
- nstate = N_DOT;
- }
- else
- s1 = 0;
-
- /* s1-> '.' after 000000 or NULL */
-
- s = strchr (fptr, '/');
- if (s == 0)
- { /* no next '/' */
- if (*(vptr-1) == '.')
- *(vptr-1) = ']';
- else if (rooted == 0)
- *vptr++ = ']';
- copyto (&vptr, &fptr, 0, (type == 1));
- state = -1;
- break;
- }
- else
- {
- while (*(s+1) == '/') /* skip multiple '/' */
- s++;
- }
-
- if ((rooted != 0)
- && (*(vptr-1) != '.'))
- {
- *vptr++ = '[';
- nstate = N_DOT;
- }
- else
- if ((nstate == N_DOT)
- && (s1 != 0)
- && (*(s+1) == 0))
- {
- if (type == 2)
- {
- *s1 = ']';
- nstate = N_CLOSED;
- }
- }
- state = 9;
- break;
-
- case 4: /* single '/' at start (9..15) */
- if (*fptr == 0)
- state = 5;
- else
- state = 6;
- break;
-
- case 5: /* just '/' at start (9) */
- if (type != 2)
- {
- *vptr++ = '[';
- nstate = N_OPEN;
- }
- strcpy (vptr, "000000");
- vptr += 6;
- if (type == 2)
- state = 7;
- else
- state = 8;
- break;
-
- case 6: /* chars following '/' at start 10..15 */
- *vptr++ = '[';
- nstate = N_OPEN;
- s = strchr (fptr, '/');
- if (s == 0) /* 10 */
- {
- if (type != 1)
- {
- strcpy (vptr, "000000]");
- vptr += 7;
- }
- copyto (&vptr, &fptr, 0, (type == 1));
- if (type == 1)
- {
- *vptr++ = ']';
- }
- state = -1;
- }
- else /* 11..15 */
- {
- if ( (type == 2)
- && (*(s+1) == 0)) /* 11(2) */
- {
- strcpy (vptr, "000000]");
- nstate = N_CLOSED;
- vptr += 7;
- }
- copyto (&vptr, &fptr, '/', (*(vptr-1) != ']'));
- state = 9;
- }
- break;
-
- case 7: /* add '.dir' and exit */
- if ((nstate == N_OPEN)
- || (nstate == N_DOT))
- {
- s = vptr-1;
- while (s > vmsname)
- {
- if (*s == ']')
- {
- break;
- }
- if (*s == '.')
- {
- *s = ']';
- break;
- }
- s--;
- }
- }
- strcpy (vptr, ".dir");
- vptr += 4;
- state = -1;
- break;
-
- case 8: /* add ']' and exit */
- *vptr++ = ']';
- state = -1;
- break;
-
- case 9: /* 17..21, fptr -> 1st '/' + 1 */
- if (*fptr == 0)
- {
- if (type == 2)
- {
- state = 7;
- }
- else
- state = 8;
- break;
- }
- s = strchr (fptr, '/');
- if (s == 0)
- {
- if (type != 1)
- {
- if (nstate == N_OPEN)
- {
- *vptr++ = ']';
- nstate = N_CLOSED;
- }
- as_dir = 0;
- }
- else
- {
- if (nstate == N_OPEN)
- {
- *vptr++ = '.';
- nstate = N_DOT;
- }
- as_dir = 1;
- }
- }
- else
- {
- while (*(s+1) == '/')
- s++;
- if ( (type == 2)
- && (*(s+1) == 0)) /* 19(2), 21(2)*/
- {
- if (nstate != N_CLOSED)
- {
- *vptr++ = ']';
- nstate = N_CLOSED;
- }
- as_dir = 1;
- }
- else
- {
- if (nstate == N_OPEN)
- {
- *vptr++ = '.';
- nstate = N_DOT;
- }
- as_dir = 1;
- }
- }
- if ( (*fptr == '.') /* check for '..' or '../' */
- && (*(fptr+1) == '.')
- && ((*(fptr+2) == '/')
- || (*(fptr+2) == 0)) )
- {
- fptr += 2;
- if (*fptr == '/')
- {
- do
- {
- fptr++;
- }
- while (*fptr == '/');
- }
- else if (*fptr == 0)
- type = 1;
- vptr--; /* vptr -> '.' or ']' */
- s1 = vptr;
- for (;;)
- {
- s1--;
- if (*s1 == '.') /* one back */
- {
- vptr = s1;
- nstate = N_OPEN;
- break;
- }
- if (*s1 == '[') /* top level reached */
- {
- if (*fptr == 0)
- {
- strcpy (s1, "[000000]");
- vptr = s1 + 8;
- nstate = N_CLOSED;
- s = 0;
- break;
- }
- else
- {
- vptr = s1+1;
- nstate = N_OPEN;
- break;
- }
- }
- }
- }
- else
- {
- copyto (&vptr, &fptr, '/', as_dir);
- if (nstate == N_DOT)
- nstate = N_OPEN;
- }
- if (s == 0)
- { /* 18,20 */
- if (type == 1)
- *vptr++ = ']';
- state = -1;
- }
- else
- {
- if (*(s+1) == 0)
- {
- if (type == 2) /* 19,21 */
- {
- state = 7;
- }
- else
- {
- *vptr++ = ']';
- state = -1;
- }
- }
- }
- break;
-
- case 10: /* 1,2 first is '.' */
- if (*fptr == '.')
- {
- fptr++;
- state = 11;
- }
- else
- state = 12;
- break;
-
- case 11: /* 2, '..' at start */
- count = 1;
- if (*fptr != 0)
- {
- if (*fptr != '/') /* got ..xxx */
- {
- return name;
- }
- do /* got ../ */
- {
- fptr++;
- while (*fptr == '/') fptr++;
- if (*fptr != '.')
- break;
- if (*(fptr+1) != '.')
- break;
- fptr += 2;
- if ((*fptr == 0)
- || (*fptr == '/'))
- count++;
- }
- while (*fptr == '/');
- }
- { /* got '..' or '../' */
- char cwdbuf[MAXPATHLEN+1];
-
- s1 = getcwd(cwdbuf, MAXPATHLEN);
- if (s1 == 0)
- {
- return ""; /* FIXME, err getcwd */
- }
- strcpy (vptr, s1);
- s = strchr (vptr, ']');
- if (s != 0)
- {
- nstate = N_OPEN;
- while (s > vptr)
- {
- s--;
- if (*s == '[')
- {
- s++;
- strcpy (s, "000000]");
- state = -1;
- break;
- }
- else if (*s == '.')
- {
- if (--count == 0)
- {
- if (*fptr == 0) /* had '..' or '../' */
- {
- *s++ = ']';
- state = -1;
- }
- else /* had '../xxx' */
- {
- state = 9;
- }
- *s = 0;
- break;
- }
- }
- }
- }
- vptr += strlen (vptr);
- }
- break;
-
- case 12: /* 1, '.' at start */
- if (*fptr != 0)
- {
- if (*fptr != '/')
- {
- return name;
- }
- fptr++;
- }
-
- {
- char cwdbuf[MAXPATHLEN+1];
-
- s1 = getcwd(cwdbuf, MAXPATHLEN);
- if (s1 == 0)
- {
- return ""; /*FIXME, err getcwd */
- }
- strcpy (vptr, s1);
- if (*fptr == 0)
- {
- state = -1;
- break;
- }
- else
- {
- s = strchr (vptr, ']');
- if (s == 0)
- {
- state = -1;
- break;
- }
- *s = 0;
- nstate = N_OPEN;
- vptr += strlen (vptr);
- state = 9;
- }
- }
- break;
- }
-
- }
- while (state > 0);
-
-
- }
-
-
- /* directory conversion done
- fptr -> filename part of input string
- vptr -> free space in vmsname
- */
-
- *vptr++ = 0;
-
- return vmsname;
- }
-
-
-
- /*
- convert from vms-style to unix-style
-
- dev:[dir1.dir2] //dev/dir1/dir2/
- */
-
- char *
- unixify (char *name)
- {
- static char piece[512];
- char *s, *p;
-
- if (strchr (name, '/') != 0) /* already in unix style */
- return name;
-
- p = piece;
- *p = 0;
-
- /* device part */
-
- s = strchr (name, ':');
-
- if (s != 0)
- {
- *s = 0;
- *p++ = '/';
- *p++ = '/';
- strcpy (p, name);
- p += strlen (p);
- *s = ':';
- }
-
- /* directory part */
-
- *p++ = '/';
- s = strchr (name, '[');
-
- if (s != 0)
- {
- s++;
- switch (*s)
- {
- case ']': /* [] */
- strcat (p, "./");
- break;
- case '-': /* [- */
- strcat (p, "../");
- break;
- case '.':
- strcat (p, "./"); /* [. */
- break;
- default:
- s--;
- break;
- }
- s++;
- while (*s)
- {
- if (*s == '.')
- *p++ = '/';
- else
- *p++ = *s;
- s++;
- if (*s == ']')
- {
- s++;
- break;
- }
- }
- if (*s != 0) /* more after ']' ?? */
- {
- if (*(p-1) != '/')
- *p++ = '/';
- strcpy (p, s); /* copy it anyway */
- }
- }
-
- else /* no '[' anywhere */
-
- {
- *p++ = 0;
- }
-
- /* force end with '/' */
-
- if (*(p-1) != '/')
- *p++ = '/';
- *p = 0;
-
- return piece;
- }
-
- /* EOF */
-